#pragma once


namespace LocalProxy{

	class CWSAAutoStartUp
	{
	public:
		CWSAAutoStartUp()
		{
			WSAStartup(MAKEWORD(1,1),&wsaData);
		}
		~CWSAAutoStartUp()
		{
			WSACleanup();
		}
	private:
		WSADATA wsaData;
	};
	class CSocket
	{
	public:
		CSocket()
			:m_s(INVALID_SOCKET)
			,m_WSAErrorCode(0)
		{

		}

		CSocket(SOCKET sock)
			:m_s(sock)
		{
			ATLASSERT(m_s!=INVALID_SOCKET);
		}

		~CSocket()
		{
			if(m_s!=SOCKET_ERROR)
			{
				closesocket(m_s);
			}
		}

		void Attach(SOCKET sock)
		{
			ATLASSERT(m_s==INVALID_SOCKET);
			m_s=sock;
			ATLASSERT(m_s!=INVALID_SOCKET);
		}

		BOOL Create(IN int af,
			IN int type,
			IN int protocol)
		{
			Attach(socket(af,type,protocol));
			return m_s!=INVALID_SOCKET;
		}

		BOOL Bind(const sockaddr_in *pAddr,int len)
		{
			return SOCKET_ERROR!=bind(m_s,(const sockaddr*)pAddr,len);
		}

		BOOL Listen(int backlog)
		{
			return SOCKET_ERROR!=listen(m_s,backlog);
		}

		SOCKET Accept(struct sockaddr_in *pAddr,int *len)
		{
			return accept(m_s,(struct sockaddr*)pAddr,len);
		}

		int Recv(char *buf,int len,int flag=0)
		{
			ATLASSERT(m_s!=SOCKET_ERROR);
			const int ret=recv(m_s,buf,len,flag);
			if(ret==0)
			{
				m_WSAErrorCode=WSAGetLastError();
				Close();
				return 0;
			}
			return ret;
		}

		int Send(const char* buf,int len,int flag=0)
		{
			ATLASSERT(m_s!=SOCKET_ERROR);
			const int ret=send(m_s,buf,len,flag);
			if(ret==SOCKET_ERROR)
			{
				m_WSAErrorCode=WSAGetLastError();
				Close();
			}
			return ret;
		}

		operator SOCKET()
		{
			return m_s;
		}

		void Close()
		{
			closesocket(m_s);
			m_s=INVALID_SOCKET;
		}

		BOOL IsValid()
		{
			return m_s!=INVALID_SOCKET;
		}

		int ErrorCode() const
		{
			return m_WSAErrorCode;
		}
	private:
		int m_WSAErrorCode;
		SOCKET m_s;
	};
}